package org.mall.modules.mq.pay;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;
import org.mall.common.api.vo.CommonResult;
import org.mall.common.constant.PayErrorCodeEnum;
import org.mall.common.constant.PayRefundStatus;
import org.mall.common.constant.PayTransactionStatusEnum;
import org.mall.common.util.ServiceExceptionUtil;
import org.mall.common.util.json.JacksonUtils;
import org.mall.modules.pay.dataobject.PayRefundDO;
import org.mall.modules.pay.dataobject.PayTransactionDO;
import org.mall.modules.pay.mapper.PayRefundMapper;
import org.mall.modules.pay.service.PayRefundService;
import org.mall.modules.pay.service.PayTransactionService;
import org.mall.modules.pay.service.impl.PayNotifyServiceImpl;
import org.mall.modules.pojo.pay.refund.PayRefundBO;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

/***
 *@author yinxucun
 *@date 2020-01-13 17:38 
 */
@Component
@Slf4j
public class UpdateAliPayRefundLister implements MessageListenerConcurrently {
    @Autowired
    PayRefundService payRefundService;
    @Autowired
    AlipayClient alipayClient;
    @Resource
    PayRefundMapper payRefundMapper;
    @Autowired
    PayTransactionService payTransactionService;
    @Autowired
    PayNotifyServiceImpl payNotifyService;

    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext context) {
        MessageExt messageExt = list.get(0);
        ConsumeConcurrentlyStatus x =((UpdateAliPayRefundLister) AopContext.currentProxy()). updateAliPaySuccess(messageExt);
        if (x != null) {
            return x;
        }

        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }

    @Transactional
    public ConsumeConcurrentlyStatus updateAliPaySuccess(MessageExt messageExt) {
        PayRefundBO payRefundBO= (PayRefundBO) JacksonUtils.parseObject(new String(messageExt.getBody()),PayRefundBO.class);
        AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
        JSONObject jsonObject=new JSONObject();
        jsonObject.put("out_request_no",payRefundBO.getRefundCode());
        jsonObject.put("out_trade_no",payRefundBO.getTradeNo());
        try {
            AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
            if (response.isSuccess()){
                if (response.getRefundStatus()!=null&&("".equals(response.getRefundStatus())||"REFUND_SUCCESS"
                        .equals(response.getRefundStatus()))){

                    PayRefundDO payRefund = payRefundMapper.selectByRefundCode(payRefundBO.getRefundCode());
                    if (payRefund == null) {
                        return ConsumeConcurrentlyStatus.RECONSUME_LATER;
                    }
                    if (!PayRefundStatus.WAITING.getValue().equals(payRefund.getStatus())) { // 校验状态，必须是待支付
                        return ConsumeConcurrentlyStatus.RECONSUME_LATER;
                    }
                    // 1.2 更新 PayRefundDO
                    PayRefundDO updatePayRefundDO = new PayRefundDO()
                            .setId(payRefund.getId())
                            .setStatus(PayRefundStatus.SUCCESS.getValue());
                    int updateCounts = payRefundMapper.update(updatePayRefundDO, PayRefundStatus.WAITING.getValue());
                    if (updateCounts == 0) { // 校验状态，必须是待支付
                        throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_REFUND_STATUS_NOT_WAITING.getCode());
                    }
                    // 2.1 判断 PayTransactionDO ，增加已退款金额
                    PayTransactionDO payTransaction = payTransactionService.getTransaction(payRefund.getTransactionId());
                    if (payTransaction == null) {
                        return ConsumeConcurrentlyStatus.RECONSUME_LATER;
                    }
                    if (!PayTransactionStatusEnum.SUCCESS.getValue().equals(payTransaction.getStatus())) { // 校验状态，必须是已支付
                        throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_STATUS_IS_NOT_SUCCESS.getCode());
                    }
                    if (payRefund.getPrice() + payTransaction.getRefundTotal() > payTransaction.getPrice()) {
                        throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_REFUND_PRICE_EXCEED.getCode());
                    }
                    // 2.2 更新 PayTransactionDO
                    updateCounts = payTransactionService.updateTransactionPriceTotalIncr(payRefund.getTransactionId(), payRefund.getPrice());
                    if (updateCounts == 0) { // 保证不超退 TODO 这种类型，需要思考下。需要返回错误，但是又要保证事务回滚
                        throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_REFUND_PRICE_EXCEED.getCode());
                    }
                    // 3 新增 PayNotifyTaskDO
                    payNotifyService.addRefundNotifyTask(payRefund);
                    // 返回结果
                    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;

                }
            }
        } catch (AlipayApiException e) {
            log.error("查询退款交易失败,订单编号:{},退款编号:{},失败原因:{}",payRefundBO.getOrderId(),payRefundBO.getRefundCode(),e.getErrMsg());
        }
        return null;
    }
}
